using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using System.IO;
using Microsoft.Xna.Framework;

namespace FishFillets.GameComponents.Helpers
{
    /// <summary>
    /// Class designed for alternate loading of content which is not converted into XNA format.
    /// </summary>
    public class AssetHelper
    {
        public Dictionary<string, Texture2D> LoadedTextures = new Dictionary<string, Texture2D>();
        public static BlendState blendColor = null, blendAlpha = null;
        public string RootDirectory { get; set; }
        public GraphicsDevice GraphicsDevice { get; set; }

        public AssetHelper(GraphicsDevice graphicsDevice, string rootDirectory)
        {
            this.GraphicsDevice = graphicsDevice;
            this.RootDirectory = rootDirectory;
        }

        ~AssetHelper()
        {
            this.UnloadAll();
        }

        /// <summary>
        /// Unloads files from specified location from cache.
        /// </summary>
        /// <param name="location">Location where the files were loaded from.</param>
        /// <returns><see cref="true"/> if any cache items were removed, otherwise <see cref="false"/></returns>
        public bool UnloadFromCache(string location)
        {
            var textures = LoadedTextures.Where(s => s.Key.StartsWith(location));
            if (textures.Any())
            {
                foreach (var texture in textures)
                {
                    LoadedTextures.Remove(texture.Key);
                }
                return true;
            }
            else return false;
        }

        public void UnloadAll()
        {
            LoadedTextures.Clear();
        }

        /// <summary>
        /// LoadTextureStream method to speed up loading Texture2Ds from pngs,
        /// as described in
        /// http://jakepoz.com/jake_poznanski__speeding_up_xna.html
        /// Credits go to Jake Poznanski who created this solution.
        /// </summary>
        /// <param name="graphics">Graphics device to use</param>
        /// <param name="location">Location of the image, root of the path is in the Content folder</param>
        /// <returns>A Texture2D with premultiplied alpha</returns>
        public Texture2D LoadTextureStream(string location)
        {
            // don't waste time with processing if the texture was already loaded
            if (LoadedTextures.ContainsKey(location))
                return LoadedTextures[location] as Texture2D;

            Texture2D file = null;
            RenderTarget2D result = null;

            using (Stream titleStream = TitleContainer.OpenStream(
                Path.Combine(RootDirectory, location + ".png")))
            {
                file = Texture2D.FromStream(GraphicsDevice, titleStream);
            }

            //Setup a render target to hold our final texture which will have premulitplied alpha values
            result = new RenderTarget2D(GraphicsDevice, file.Width, file.Height);

            GraphicsDevice.SetRenderTarget(result);
            GraphicsDevice.Clear(Color.Black);

            //Multiply each color by the source alpha, and write in just the color values into the final texture
            if (blendColor == null)
            {
                blendColor = new BlendState();
                blendColor.ColorWriteChannels = ColorWriteChannels.Red | ColorWriteChannels.Green | ColorWriteChannels.Blue;

                blendColor.AlphaDestinationBlend = Blend.Zero;
                blendColor.ColorDestinationBlend = Blend.Zero;

                blendColor.AlphaSourceBlend = Blend.SourceAlpha;
                blendColor.ColorSourceBlend = Blend.SourceAlpha;
            }

            SpriteBatch spriteBatch = new SpriteBatch(GraphicsDevice);
            spriteBatch.Begin(SpriteSortMode.Immediate, blendColor);
            spriteBatch.Draw(file, file.Bounds, Color.White);
            spriteBatch.End();

            //Now copy over the alpha values from the PNG source texture to the final one, without multiplying them
            if (blendAlpha == null)
            {
                blendAlpha = new BlendState();
                blendAlpha.ColorWriteChannels = ColorWriteChannels.Alpha;

                blendAlpha.AlphaDestinationBlend = Blend.Zero;
                blendAlpha.ColorDestinationBlend = Blend.Zero;

                blendAlpha.AlphaSourceBlend = Blend.One;
                blendAlpha.ColorSourceBlend = Blend.One;
            }

            spriteBatch.Begin(SpriteSortMode.Immediate, blendAlpha);
            spriteBatch.Draw(file, file.Bounds, Color.White);
            spriteBatch.End();

            //Release the GPU back to drawing to the screen
            GraphicsDevice.SetRenderTarget(null);

            LoadedTextures.Add(location, result as Texture2D);
            return result as Texture2D;
        }
    }
}
